package eiisan.forkjointest.countedcompleter;

import eiisan.forkjointest.TreeNode;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CountedCompleter;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;

/**
 * 可以参考 such as {@link java.util.concurrent.ConcurrentHashMap.BulkTask}
 * @param <E>
 */
public class SearcherTree<E extends TreeNode> extends CountedCompleter<E> {
    final List<E> array;
    final AtomicReference<E> result;
    final Predicate<E> predicate;

    public SearcherTree(CountedCompleter<?> p, List<E> array, AtomicReference<E> result, Predicate<E> predicate) {
        super(p);
        this.array = array;
        this.result = result;
        this.predicate = predicate;
    }

    @Override
    public E getRawResult() {
        return result.get();
    }


    public void compute() {
        for (int i = 0; i < array.size() && result.get() == null; i++) {
            E x = array.get(i);
            if (!x.getChildNodes().isEmpty()) {
                addToPendingCount(1);
                new SearcherTree(this, x.getChildNodes(), result, predicate).fork();
            }
            if (matches(x) && result.compareAndSet(null, x)) {
                quietlyCompleteRoot(); // root task is now joinable
                break;
            }
        }
        tryComplete(); // normally complete whether or not found
    }

/*  这种需要操作list add，执行效率慢
    public void compute() {
        List<TreeNode> childs = new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            E x = array.get(i);
            childs.addAll(x.getChildNodes());
        }
        if (result.get() == null && !childs.isEmpty()) {
            addToPendingCount(1);
            new SearcherTree(this, childs, result, predicate).fork();
        }
        for (int i = 0; i < array.size() && result.get() == null; i++) {
            E x = array.get(i);
            if (matches(x) && result.compareAndSet(null, x)) {
                quietlyCompleteRoot(); // root task is now joinable
                break;
            }
        }
        tryComplete(); // normally complete whether or not found
    }
    */

    private boolean matches(E e) {
        boolean test = predicate.test(e);
        if (test) {
            System.out.println(" ====>>> " + e.getId());
        }
        return test;
    } // return true if found


    public static <E extends TreeNode> E search(List<E> list, Predicate<E> predicate) {
        return new SearcherTree<E>(null, list, new AtomicReference<E>(), predicate).invoke();
    }
}
